//
//  EGExcelTable.swift
//  EGExcel
//
//  Created by youzy01 on 2021/4/15.
//

import UIKit

private let headerId = "HeaderId"
private let cellId = "CellId"

class EGExcelTable: UIView {
    lazy var layout = UICollectionViewFlowLayout()

    lazy var collectionView: UICollectionView = {
        let view = UICollectionView(frame: .zero, collectionViewLayout: layout)
        view.backgroundColor = .clear
        view.showsVerticalScrollIndicator = false
        view.showsHorizontalScrollIndicator = false
        view.bounces = false
        view.register(EGExcelTableHeader.self, forSupplementaryViewOfKind: UICollectionView.elementKindSectionHeader, withReuseIdentifier: headerId)
        view.register(EGExcelTableCell.self, forCellWithReuseIdentifier: cellId)
        view.dataSource = self
        view.delegate = self
        return view
    }()

    override var intrinsicContentSize: CGSize {
        return layout.collectionViewContentSize
    }

    var didSelected: ((_ header: TextConvertible, _ label: UILabel, _ row: Int) -> Void)?

    private(set) var header: TextConvertible
    private(set) var dataSource: [TextConvertible]

    init(header: TextConvertible, dataSource: [TextConvertible]) {
        self.header = header
        self.dataSource = dataSource
        super.init(frame: .zero)

        NotificationCenter.default.addObserver(self, selector: #selector(notifcationAction(_:)), name: .tableDidScroll, object: nil)

        let list = [header] + dataSource
        let textWidth = list.map { $0.widthForFont(UIFont.systemFont(ofSize: 12), height: 40) }.max() ?? 50
        let width = textWidth + 20

        layout.sectionHeadersPinToVisibleBounds = true
        layout.itemSize = CGSize(width: width, height: 40)
        layout.headerReferenceSize = CGSize(width: width, height: 40)
        layout.minimumLineSpacing = 1
        layout.sectionInset = UIEdgeInsets(top: 0, left: 0, bottom: 0, right: 0)

        collectionView.translatesAutoresizingMaskIntoConstraints = false
        addSubview(collectionView)
        NSLayoutConstraint.activate([
            collectionView.topAnchor.constraint(equalTo: topAnchor),
            collectionView.bottomAnchor.constraint(equalTo: bottomAnchor),
            collectionView.leftAnchor.constraint(equalTo: leftAnchor),
            collectionView.rightAnchor.constraint(equalTo: rightAnchor),
            collectionView.widthAnchor.constraint(equalToConstant: width)
        ])
    }

    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }

    override func layoutSubviews() {
        layout.itemSize = CGSize(width: frame.width, height: 40)
        layout.headerReferenceSize = CGSize(width: frame.width, height: 40)
    }

    func configure(header: TextConvertible, dataSource: [TextConvertible]) {
        self.header = header
        self.dataSource = dataSource
        collectionView.reloadData()
    }

    @objc func notifcationAction(_ sender: Notification) {
        guard let object = sender.object as? EGExcelTable, object != self else {
            return
        }
        guard let y = sender.userInfo?["y"] as? CGFloat else {
            return
        }
        collectionView.setContentOffset(CGPoint(x: 0, y: y), animated: false)
    }
}

extension EGExcelTable: UICollectionViewDataSource {
    func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        return dataSource.count
    }

    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: cellId, for: indexPath)
        let text = dataSource[indexPath.item]
        if text.isAttributesText {
            (cell as? EGExcelTableCell)?.textLabel.attributedText = text as? NSAttributedString
        } else {
            (cell as? EGExcelTableCell)?.textLabel.text = text as? String
        }
        return cell
    }

    func collectionView(_ collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, at indexPath: IndexPath) -> UICollectionReusableView {
        let headerView = collectionView.dequeueReusableSupplementaryView(ofKind: UICollectionView.elementKindSectionHeader, withReuseIdentifier: headerId, for: indexPath)
        if header.isAttributesText {
            (headerView as? EGExcelTableHeader)?.textLabel.attributedText = header as? NSAttributedString
        } else {
            (headerView as? EGExcelTableHeader)?.textLabel.text = header as? String
        }
        return headerView
    }
}

extension EGExcelTable: UICollectionViewDelegate {
    func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
        guard let cell = collectionView.cellForItem(at: indexPath) as? EGExcelTableCell else {
            return
        }
        didSelected?(header, cell.textLabel, indexPath.item)
    }
}

extension EGExcelTable: UIScrollViewDelegate {
    func scrollViewDidScroll(_ scrollView: UIScrollView) {
        let y = scrollView.contentOffset.y
        if scrollView.isDragging {
            NotificationCenter.default.post(name: .tableDidScroll, object: self, userInfo: ["y": y])
        }
    }
}

extension Notification.Name {
    static let tableDidScroll = Notification.Name.init("tableDidScroll")
}
